//---------------------------------------------------------------------------
#include <vcl\vcl.h>
#include <Math.h>
#pragma hdrstop

#include "Recognize.h"
//---------------------------------------------------------------------------

#define PHI		3.14159264
//#define M_PI	PHI
//#define M_PI_2	(PHI/2)

#define	DATA_FILE_NAME	"HC.DAT"


void TRecognize::Sizing(void)
{
    const int X=99,Y=99;
    int maxx=0,maxy=0;
    int minx=X,miny=Y;
    int i;
    double mag;
    for(i=0;i<=ppattern->point;i++){
		if(ppattern->GetX(i)!=0||ppattern->GetY(i)!=0){
			if(ppattern->GetX(i)>maxx) maxx=ppattern->GetX(i);
			if(ppattern->GetY(i)>maxy) maxy=ppattern->GetY(i);
			if(ppattern->GetX(i)<minx) minx=ppattern->GetX(i);
			if(ppattern->GetY(i)<miny) miny=ppattern->GetY(i);
		}
    }
    if(maxx!=minx) mag=(float)X/(float)(maxx-minx);
    else mag=100;
    if(maxy!=miny)
	if(mag>((float)Y/(float)(maxy-miny)))
	    mag=(float)Y/(float)(maxy-miny);
    for(i=0;i<=ppattern->point;i++){
		if(ppattern->GetX(i)!=0||ppattern->GetY(i)!=0){
			ppattern->SetX(i,(int)((ppattern->GetX(i)-minx)*mag+1));
			ppattern->SetY(i,(int)((ppattern->GetY(i)-miny)*mag+1));
		}
    }
    ppattern->maxx=(int)((maxx-minx)*mag+1);
    ppattern->maxy=(int)((maxy-miny)*mag+1);
}

int TRecognize::Distance(int x1,int y1,int x2,int y2)
{
    const int dist=10;
    if((x1==0&&y1==0)||(x2==0&&y2==0)) return TRUE;
    if( sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2))>dist ) return TRUE;
    else return FALSE;
}

void TRecognize::PreProcessing(void)
{
	int i;
    TIPattern dest;
    dest.maxx=ppattern->maxx;
    dest.maxy=ppattern->maxy;
    dest.point=0;

    // FILTERING
    dest.SetX(0,ppattern->GetX(0));
    dest.SetY(0,ppattern->GetY(0));
    for(i=1;i<=ppattern->point;i++){
		if(Distance(dest.GetX(dest.point),dest.GetY(dest.point),
							ppattern->GetX(i),ppattern->GetY(i))==TRUE){
			dest.point++;
			dest.SetX(dest.point,ppattern->GetX(i));
			dest.SetY(dest.point,ppattern->GetY(i));
		}
    }

    //SMOOTHING
    ppattern->point=0;
    int srcang,patternang=-2;
    for(i=0;i<dest.point;i++){

	if(i==0) {
	    ppattern->SetX(ppattern->point,dest.GetX(i));
	    ppattern->SetY(ppattern->point,dest.GetY(i));
	}
	else if (dest.GetX(i)==0&&dest.GetY(i)==0) {
		ppattern->point++;
		ppattern->SetX(ppattern->point,0);
		ppattern->SetY(ppattern->point,0);
		ppattern->point++;
		ppattern->SetX(ppattern->point,dest.GetX(i+1));
		ppattern->SetY(ppattern->point,dest.GetY(i+1));
		patternang=-2;
		i++;
	}
	else {
	    if(patternang==-2){
			ppattern->point++;
			ppattern->SetX(ppattern->point,dest.GetX(i));
			ppattern->SetY(ppattern->point,dest.GetY(i));
			patternang=0;
	    }
	    else {
			srcang=GetAngle(dest.GetX(i-1),dest.GetY(i-1),dest.GetX(i),dest.GetY(i));
			patternang=GetAngle(ppattern->GetX(ppattern->point-1),ppattern->GetY(ppattern->point-1),
				ppattern->GetX(ppattern->point),ppattern->GetY(ppattern->point));
			if(patternang==srcang||patternang==srcang+1||patternang==srcang-1||
				(patternang==11&&srcang==0)||(patternang==0&&srcang==11));
			else ppattern->point++;

			ppattern->SetX(ppattern->point,dest.GetX(i));
			ppattern->SetY(ppattern->point,dest.GetY(i));
	    }
	}
    }
    ppattern->point++;
    ppattern->SetX(ppattern->point,0);
    ppattern->SetY(ppattern->point,0);

}

int	TRecognize::GetAngle(int x1,int y1,int x2,int y2)
{
    double x,y,angle;
    x=x2-x1;y=y1-y2;
    if(x!=0) angle=atan(y/x);
	else angle=M_PI_2;
    angle=angle*180/M_PI;
    if(x<0&&y>0) angle=180+angle;
    if(x<0&&y<0) angle=180+angle;
    if(x>0&&y<0) angle=360+angle;
    if(x==0&&y>0) angle=90;
    if(x==0&&y<0) angle=270;
    if(y==0&&x<0) angle=180;
    return (int)(angle/30);
}
int TRecognize::SubRecognizing(void)
{
    int dir[100];
    int i,match,dirp;
    int angle=0;
    char data;
    int fdata[50];
    FILE *f;
    //DIRECTION
    for(i=0;i<ppattern->point-1;i++){
		dir[i]=angle;
    }
    dirp=0;
    for(i=0;i<ppattern->point;i++){
		angle=GetAngle(ppattern->GetX(i),ppattern->GetY(i),ppattern->GetX(i+1),ppattern->GetY(i+1));
		if(ppattern->GetX(i)==0&&ppattern->GetY(i)==0) dir[dirp++]=-1;
		else if(ppattern->GetX(i+1)!=0||ppattern->GetY(i+1)!=0) dir[dirp++]=angle;
    }
    dir[dirp++]=-1;
    dir[dirp]=-1;

//    dirp=0;

    f=fopen(DATA_FILE_NAME,"r");
	if(f==NULL) return FALSE;

//    tmp=0;
    while(!feof(f)){
		fscanf(f,"%c",&data);
		fgetc(f);
		for(i=0;i<50;i++){
			fscanf(f,"%d",&fdata[i]);
			fgetc(f);
			if(fdata[i]==-1&&fdata[i-1]==-1) break;
		}
		match=TRUE;
		dirp=0;
		for(i=0;i<50;i++){
			if(dir[dirp]!=fdata[i]) match=FALSE;
			if(dir[dirp]==-1&&dir[dirp-1]==-1) break;
			dirp++;
		}
		if (match==TRUE) {
			fclose(f);
			return (int)data;
		}
//		gotoxy(1,1);printf("%c %3d",data,tmp++);
    }
    fclose(f);
    
	return FALSE;
}
int TRecognize::DoRecognize(TIPattern *ippattern)
{
    int result;
	ppattern = ippattern;
    Sizing ();
    PreProcessing();
    result=SubRecognizing();
    return result;
}


